﻿using System;
using System.Linq.Expressions;

namespace X23.Util.LinqUtil
{
    
    //https://www.nhooo.com/linq/linq-expression.html
    public static class ExpressionUtil
    {
        public static Expression<Func<TSource, bool>> And<TSource>(this Expression<Func<TSource, bool>> a, Expression<Func<TSource, bool>> b)
        {
            ParameterExpression replaceWith = Expression.Parameter(typeof(TSource), "root");
            return Expression.Lambda<Func<TSource, bool>>(Expression.And(ParameterExpressionReplacer.Replace(a.Body, replaceWith), ParameterExpressionReplacer.Replace(b.Body, replaceWith)), new ParameterExpression[] { replaceWith });
        }

    }

    public class ParameterExpressionReplacer : ExpressionVisitor
    {
        // Fields
        private ParameterExpression replaceWith;
        private ParameterExpressionReplacer(ParameterExpression replaceWith)
        {
            this.replaceWith = replaceWith;
        }

        // Methods
        public static Expression Replace(Expression expression, ParameterExpression replaceWith) =>
            new ParameterExpressionReplacer(replaceWith).Visit(expression);

        protected override Expression VisitParameter(ParameterExpression node) =>
            replaceWith;

    }
}
